package main

import (
	"encoding/json"
	"fmt"
)

//成员变量首字母必须大写
type jsonStr struct {
	Company string
	Subjec []string
	Isok bool
	Price float64
}

//对json进行二次编码,可以将大写的成员变量转换成小写，也能设置一下成员变量不输出在屏幕上,使用减号不是下划线
type jsonEncode struct {
	Company string `json:"-"`
	Subjec  []string `json:"subjec"`
	Isok    bool `json:"isok"`
	Price   float64 `json:"price"`
}

//json解析到结构体
type strJson struct {
	Company string   `json:"company"`
	Subjec  []string `json:"subjec"`
	Isok    bool     `json:"isok"`
	Price   float64  `json:"price"`
}

func main()  {
	//使用结构体生成json
	a := jsonStr{"baidu", []string{"Go", "C++", "PHP"}, true, 666.666}

	//编码生成json文本
	//str, err := json.Marshal(a)

	//格式化打印
	str, err := json.MarshalIndent(a, "", "	")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(string(str))

	b := jsonEncode{"baidu", []string{"Go", "C++", "PHP"}, true, 666.666}

	strb, errb := json.MarshalIndent(b, "", "	")
	if errb != nil {
		fmt.Println(errb)
		return
	}
	fmt.Println(string(strb))

	//通过map创建
	c := make(map[string]interface{})
	c["Company"] = "baidu"
	c["Subjec"] = []string{"Go", "C++", "PHP"}
	c["Isok"] = true
	c["Price"] = 666.666
	strc, errc := json.MarshalIndent(c, "", "	")
	if errc != nil {
		fmt.Println(errc)
		return
	}
	fmt.Println(string(strc))

	//json解析到结构体
	json_str := `{
	"company": "baidu",
	"subjec": [
		"Go",
		"C++",
		"PHP"
	],
	"isok": true,
	"price": 666.666
}`
	var tmp strJson
	//json.Unmarshal他是将一个切片的内容放入另一个空接口中，他接受的是一个切片，所以我们要把原始的json数据转化为切片，([]byte(json_str)这个相当于
	//string()，就是数据类型的函数，讲一个数据类型转换为切片，他只返回一个error，当解析失败的时候，如果解析成功，他不返回解析后的数据，所以我们这里传入
	//一个地址，而不是一个值
	errjs := json.Unmarshal([]byte(json_str), &tmp)
	if errjs != nil {
		fmt.Println(errjs)
		return
	}
	fmt.Printf("%+v\n", tmp)

	//只要json里边的部分数据,单是要保证成员变量和json里边的key一样，如果json里边是小写的，定义结构体是要进行二次编码
	type aaa struct {
		Subjec []string `json:"subjec"`
	}

	var bbb aaa
	errjs = json.Unmarshal([]byte(json_str), &bbb)
	if errjs != nil {
		fmt.Println(errjs)
		return
	}
	fmt.Printf("%+v\n", bbb)

	//json解析到map
	m := make(map[string]interface{})
	errjs  = json.Unmarshal([]byte(json_str), &m)
	if errjs != nil {
		fmt.Println(errjs)
		return
	}
	fmt.Printf("%+v\n", m)

	//使用类型断言获取每一个值,json里边的切片是空接口类型的，不是字符串或者其他类型，[]interface{}
	//b1.(type)必须结合if或者switch使用，不能单独执行
	for key, value := range m{
		switch data := value.(type) {
		case string:
			fmt.Printf("map[%s] = %v,类型为string\n", key, data)
		case bool:
			fmt.Printf("map[%s] = %v,类型为bool\n", key, data)
		case float64:
			fmt.Printf("map[%s] = %v,类型为float64\n", key, data)
		case []interface{}:
			fmt.Printf("map[%s] = %v,类型为[]interface{}\n", key, data)
		}
	}
}